commonlibsse_ng\skse\interfaces/
serialization.rs1use core::ffi::c_void;
11
12use crate::re::BSCoreTypes::{FormID, VMHandle};
13use crate::skse::api::{ApiStorageError, get_plugin_handle};
14use crate::skse::impls::stab::SKSESerializationInterface;
15
16const U32_MAX: usize = u32::MAX as usize;
17
18#[derive(Debug, Clone)]
24pub struct SerializationInterface(&'static SKSESerializationInterface);
25
26impl SerializationInterface {
27 pub const VERSION: u32 = 4;
29
30 #[inline]
32 pub(crate) const fn new(interface: &'static SKSESerializationInterface) -> Self {
33 Self(interface)
34 }
35
36 #[inline]
38 pub const fn version(&self) -> u32 {
39 self.0.version
40 }
41
42 #[inline]
48 pub fn set_unique_id(&self, uid: u32) -> Result<(), ApiStorageError> {
49 unsafe { (self.0.SetUniqueId)(get_plugin_handle()?, uid) };
50 Ok(())
51 }
52
53 #[inline]
59 pub fn set_form_delete_callback(
60 &self,
61 callback: fn(handle: VMHandle),
62 ) -> Result<(), ApiStorageError> {
63 #[allow(clippy::fn_to_numeric_cast_any)]
64 let void_f = (callback as *mut fn(handle: VMHandle)).cast();
65 unsafe { ((self.0).SetFormDeleteCallback)(get_plugin_handle()?, void_f) }
66
67 Ok(())
68 }
69
70 #[inline]
76 pub fn set_load_callback(&self, callback: fn(&Self)) -> Result<(), ApiStorageError> {
77 #[allow(clippy::fn_to_numeric_cast_any)]
78 let void_f = (callback as *mut fn(&Self)).cast();
79 unsafe { ((self.0).SetLoadCallback)(get_plugin_handle()?, void_f) }
80 Ok(())
81 }
82
83 #[inline]
89 pub fn set_revert_callback(&self, callback: fn(&Self)) -> Result<(), ApiStorageError> {
90 #[allow(clippy::fn_to_numeric_cast_any)]
91 let void_f = (callback as *mut fn(&Self)).cast();
92 unsafe { ((self.0).SetRevertCallback)(get_plugin_handle()?, void_f) }
93 Ok(())
94 }
95
96 #[inline]
102 pub fn set_save_callback(&self, callback: fn(&Self)) -> Result<(), ApiStorageError> {
103 #[allow(clippy::fn_to_numeric_cast_any)]
104 let callback = (callback as *mut fn(&Self)).cast();
105 unsafe { ((self.0).SetSaveCallback)(get_plugin_handle()?, callback) }
106 Ok(())
107 }
108
109 #[inline]
114 pub fn write_record<T>(&self, record_type: u32, version: u32, buf: &T) -> Result<(), Error> {
115 let data_size: usize = core::mem::size_of::<T>();
116
117 if data_size > U32_MAX {
118 return Err(Error::TooLargeWriteRecordData { actual: data_size });
119 }
120
121 let void_buf = (buf as *const T).cast::<c_void>();
122 let result =
123 unsafe { ((self.0).WriteRecord)(record_type, version, void_buf, data_size as u32) };
124
125 if result { Ok(()) } else { Err(Error::WriteRecordError) }
126 }
127
128 #[inline]
133 pub fn open_recode(&self, record_type: u32, version: u32) -> Result<(), Error> {
134 if unsafe { ((self.0).OpenRecord)(record_type, version) } {
135 Ok(())
136 } else {
137 Err(Error::OpenRecordError)
138 }
139 }
140
141 #[inline]
146 pub fn write_record_data<T>(&self, buf: &[T]) -> Result<(), Error> {
147 let buf_len = buf.len();
148
149 match buf_len {
150 0 => Ok(()),
151 1..=U32_MAX => {
152 let result =
153 unsafe { ((self.0).WriteRecordData)(buf.as_ptr().cast(), buf_len as u32) };
154 if result { Ok(()) } else { Err(Error::WriteRecordDataError) }
155 }
156 too_large_size => Err(Error::TooLargeWriteRecordData { actual: too_large_size }),
157 }
158 }
159
160 #[inline]
165 pub fn read_record_data<T>(&self, buf: &mut [T]) -> u32 {
166 unsafe { (self.0.ReadRecordData)(buf.as_mut_ptr().cast(), buf.len() as u32) }
167 }
168
169 #[inline]
174 pub fn get_next_record_info(
175 &self,
176 record_type: &mut u32,
177 version: &mut u32,
178 length: &mut u32,
179 ) -> Result<(), Error> {
180 unsafe {
181 let result = (self.0.GetNextRecordInfo)(record_type, version, length);
182 if result { Ok(()) } else { Err(Error::GetNextRecordInfoError) }
183 }
184 }
185
186 #[inline]
191 pub fn resolve_form_id(&self, old: FormID, new: &mut FormID) -> Result<(), Error> {
192 unsafe {
193 let result = (self.0.ResolveFormId)(old.get(), &mut new.get());
194 if result { Ok(()) } else { Err(Error::ResolveFormIdError) }
195 }
196 }
197
198 #[inline]
203 pub fn resolve_handle(&self, old: VMHandle, new: &mut VMHandle) -> Result<(), Error> {
204 let result = unsafe { (self.0.ResolveHandle)(old.get(), &mut new.get()) };
205 if result { Ok(()) } else { Err(Error::ResolveHandleError) }
206 }
207}
208
209#[derive(Debug, snafu::Snafu)]
211pub enum Error {
212 WriteRecordError,
214
215 WriteRecordDataError,
217
218 TooLargeWriteRecordData { actual: usize },
220
221 OpenRecordError,
223
224 GetNextRecordInfoError,
226
227 ResolveFormIdError,
229
230 ResolveHandleError,
232}